<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    //  作用域链（Scope Chain）
    //     作用域链是由多个作用域组成的链条，用于解决变量的查找问题。
    //     当访问一个变量时，JavaScript 会按顺序查找作用域链中的各个作用域，
    //     直到找到该变量或到达最外层的全局作用域。

    // 作用域链的工作原理
    //     当代码执行时，JavaScript 会创建一个执行上下文（Execution Context）。
    //     每个执行上下文都会有一个与之关联的作用域链。作用域链包含了当前执行上下文的作用域，
    //          以及所有父执行上下文的作用域。
    //     查找一个变量时，JavaScript 引擎首先在当前执行上下文的作用域中查找，如果没找到，
    //          则继续查找父执行上下文，直到找到变量或到达全局作用域。

    let globalVar = "I am global";

    function outerFunction() {
    let outerVar = "I am outer";

    function innerFunction() {
        let innerVar = "I am inner";
        console.log(globalVar);  // 从全局作用域查找
        console.log(outerVar);   // 从 outerFunction 的作用域查找
        console.log(innerVar);   // 在当前作用域内查找
    }

    innerFunction();
    }

    outerFunction();
    // 执行过程：
    //     innerFunction 被调用时，会创建一个执行上下文，包含它自己的作用域（即 innerVar）
    //     以及它的父作用域 outerFunction 和最外层的 globalVar。

    //     JavaScript 引擎首先查找 innerVar，如果找不到，它会继续查找外部的作用域链。

    //     在 innerFunction 中查找 outerVar 和 globalVar，因为它们分别在 outerFunction 和全局作用域中。


    // 词法作用域（Lexical Scope）
    //         JavaScript 使用词法作用域，也就是说，函数的作用域是在代码编写时就决定的，
    //         而不是在执行时决定的。即使函数在另一个作用域中执行，
    //         它依然能够访问它定义时所在作用域的变量。

    function outerFunction() {
        let outerVar = "I am outer";

        function innerFunction() {
            console.log(outerVar);  // 访问 outerVar，即使它是外部函数的变量
        }

        return innerFunction;
    }

    const myFunc = outerFunction();
    myFunc();  // 输出: I am outer
    // 在这个例子中，myFunc 是 outerFunction 返回的 innerFunction，
    // 即使 myFunc 在 outerFunction 执行完之后调用，innerFunction 
    // 依然能访问到 outerVar。这就是词法作用域的表现。
</script>
</html>